Skip to content

fix(mcp): propagate cfg.DefaultTenant to MCP fallback (RAN-22)#33

Merged
aksOps merged 2 commits into
mainfrom
ran22-default-tenant-propagation
Apr 26, 2026
Merged

fix(mcp): propagate cfg.DefaultTenant to MCP fallback (RAN-22)#33
aksOps merged 2 commits into
mainfrom
ran22-default-tenant-propagation

Conversation

@aksOps

@aksOps aksOps commented Apr 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Wire cfg.DefaultTenant into the MCP server at startup via SetDefaultTenant. Without this, header-less MCP requests fell back to the hardcoded "default" (storage.DefaultTenantID) and ignored deployments that override DEFAULT_TENANT.
  • Surface the resolved default tenant in the MCP-init log line (operability).
  • Add an HTTP-transport unit test that drives the real fallback path through ServeHTTP: asserts the constructor default, the no-op semantics of SetDefaultTenant(""), that a header-less find_similar_logs call scopes to the configured tenant, and that an explicit X-Tenant-ID header still wins over the configured default.

The original ticket also flagged a startup vector-hydration site (main.go:337 using a bare appCtx). That concern is moot post-RAN-20: hydration now uses ListRecentHighSeverityLogsAllTenants which is cross-tenant by design and tags each row with its own TenantID via vectorIdx.Add. No second fix needed; documented in the commit body.

Resolves RAN-22. Builds on RAN-19 and RAN-20.

Test plan

  • go vet ./... clean
  • go build clean
  • go test -count=1 -v -run TestSetDefaultTenant_PropagatesToHTTPTransport ./internal/mcp/... — PASS
  • Regression sweep: go test -count=1 ./internal/mcp/... ./internal/api/... ./internal/vectordb/... ./internal/storage/... — all PASS
  • Targeted regression: TestFindSimilarLogs_TenantIsolation, TestFindSimilarLogs_NoTenantFallsBackToDefault, TestMCP_TenantIsolation_AllGraphRAGTools, TestMCP_TenantIsolation_DrainClusterIDsStayPerTenant — all PASS
  • Manual smoke (optional): boot with DEFAULT_TENANT=acme, hit POST /mcp with no X-Tenant-ID for a tools/call, confirm response is acme-scoped and the startup log line shows default_tenant=acme.

🤖 Generated with Claude Code

aksOps and others added 2 commits April 25, 2026 18:48
Startup never called mcpServer.SetDefaultTenant, so header-less MCP
requests fell back to the hardcoded "default" tenant via
storage.DefaultTenantID -- ignoring DEFAULT_TENANT in deployments that
override it. Wire cfg.DefaultTenant in at MCP construction and surface
the resolved value in the startup log line.

Add an HTTP-transport unit test (TestSetDefaultTenant_PropagatesToHTTPTransport)
that exercises the actual fallback path through ServeHTTP: it asserts
the constructor default, the no-op semantics of SetDefaultTenant(""),
and that a header-less tools/call for find_similar_logs scopes to the
configured tenant. The explicit-header path is also re-checked to
confirm precedence (header wins over default) was not inverted.

The startup vector hydration concern in the original ticket is moot:
RAN-20 replaced the bare-appCtx tenant-scoped GetLogsV2 call with
ListRecentHighSeverityLogsAllTenants, which is cross-tenant by design
and tags each row with its own TenantID via vectorIdx.Add.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…nforced

Address review feedback on RAN-22 (PR #33): the previous test only
exercised SetDefaultTenant, which existed before this branch -- so
removing the main.go wiring would not have failed any test.

Move defaultTenant from a post-construction setter to a required
leading parameter on mcp.New. This turns the wiring contract into a
compile-time check: removing or omitting cfg.DefaultTenant in main.go
is now a build failure, not a silent regression. The runtime
SetDefaultTenant setter is retained for future config-reload paths.

Tests:
  - TestNew_DefaultTenant_FromConstructor exercises the constructor's
    fallback semantics (empty -> storage.DefaultTenantID; non-empty
    preserved verbatim) and confirms SetDefaultTenant runtime override
    still works without clobbering on empty input.
  - TestNew_DefaultTenant_FlowsThroughHTTPTransport drives the
    JSON-RPC HTTP handler with no X-Tenant-ID header on a server built
    via New("acme", ...) and asserts acme-scoped results, header
    precedence over the default, and that SetDefaultTenant runtime
    override flows through the same transport path.

internal/mcp/tenant_isolation_test.go updated for the new signature
(passes "" to preserve existing storage.DefaultTenantID semantics).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@sonarqubecloud

Copy link
Copy Markdown

@aksOps aksOps merged commit 4e0a4a2 into main Apr 26, 2026
11 checks passed
@aksOps aksOps deleted the ran22-default-tenant-propagation branch April 26, 2026 01:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant